#include <iostream>
#include <vector>
using namespace std;


/////////////////////////////////////////////////////////////////////////
#include<algorithm>

// struct Goods
// {
// 	string _name; // 名字
// 	double _price; // 价格
// 	int _evaluate; // 评价
// 	//...

// 	Goods(const char* str, double price, int evaluate)
// 		:_name(str)
// 		, _price(price)
// 		, _evaluate(evaluate)
// 	{}
// };

// struct Compare1
// {
// 	bool operator()(const Goods& gl, const Goods& gr)
// 	{
// 		return gl._price < gr._price;
// 	}
// };

// struct Compare2
// {
// 	bool operator()(const Goods& gl, const Goods& gr)
// 	{
// 		return gl._price > gr._price;
// 	}
// };

// int main()
// {
// 	vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
// 3 }, { "菠萝", 1.5, 4 } };

// 	sort(v.begin(), v.end(), Compare1());
// 	sort(v.begin(), v.end(), Compare2());

// 	// 价格升序
// 	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool
// 		{
// 			return g1._price < g2._price;
// 		});

// 	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool
// 		{
// 			return g1._price > g2._price;
// 		});

// 	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool
// 		{
// 			return g1._evaluate < g2._evaluate;
// 		});

// 	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool
// 		{
// 			return g1._evaluate > g2._evaluate;
// 		});


// 	return 0;
// }






// lambda 匿名函数的对象
// int main()
// {
// 	auto add1 = [](int x, int y)->int {return x + y; };
// 	cout << add1(1, 2) << endl;

// 	auto func1 = []()->int
// 	{
// 		cout << "hello ltw" << endl;
// 		cout << "hello world" << endl;
// 		return 0;
// 	};

// 	func1();

// 	// 返回值类型可自动推导类型，所以可以省略
// 	// 无参数可以省略
// 	auto func2 = []
// 	{
// 		cout << "hello ltw" << endl;
// 		cout << "hello world" << endl;
// 		return 0;
// 	};

// 	cout << func2() << endl;

// 	auto func3 = []
// 	{
// 		cout << "hello ltw" << endl;
// 		cout << "hello world" << endl;
// 	};

// 	func3();

// 	return 0;
// }





// int main()
// {
// 	int a = 0, b = 1;

// 	auto swap1 = [](int& x, int& y)
// 	{
// 		// 只能用当前lambda局部域和捕捉的对象
// 		int tmp = x;
// 		x = y;
// 		y = tmp;
// 	};

// 	swap1(a, b);

// 	// 传值捕捉本质是一种拷贝,并且const修饰了
// 	// mutable相当于去掉const属性，可以修改了
// 	// 但是修改了不会影响外面被捕捉的值，因为是一种拷贝
// 	auto swap2 = [a, b]()mutable
// 	{
// 		int tmp = a;
// 		a = b;
// 		b = tmp;
// 	};

// 	swap2();

// 	auto swap3 = [&a, &b]()
// 	{
// 		int tmp = a;
// 		a = b;
// 		b = tmp;
// 	};

// 	swap3();

// 	return 0;
// }





// int x = 0;

// int main()
// {
// 	// 只能用当前lambda局部域和捕捉的对象和全局对象

// 	int a = 0, b = 1, c = 2, d = 3;
// 	// 所有值传值捕捉
// 	auto func1 = [=]
// 	{
// 		int ret = a + b + c + d + x;
// 		return ret;
// 	};
	
// 	// 所有值传引用捕捉
// 	auto func2 = [&]
// 	{
// 		a++;
// 		b++;
// 		c++;
// 		d++;
// 		int ret = a + b + c + d;
// 		return ret;
// 	};

// 	// 混合捕捉
// 	auto func3 = [&a, b]
// 	{
// 		a++;
// 		// b++;
// 		int ret = a + b;
// 		return ret;
// 	};

// 	// 混合捕捉
// 	// 所有值以引用方式捕捉，d用传值捕捉
// 	auto func4 = [&, d]
// 	{
// 		a++;
// 		b++;
// 		c++;
// 		//d++;

// 		int ret = a + b + c + d;
// 	};

// 	auto func5 = [=, &d]() mutable
// 	{
// 		a++;
// 		b++;
// 		c++;
// 		d++;
// 		int ret = a + b + c + d;
// 	};

// 	return 0;
// }





// lambda 匿名函数的对象
// class Rate
// {
// public:
// 	Rate(double rate) : _rate(rate)
// 	{}

// 	double operator()(double money, int year)
// 	{
// 		return money * _rate * year;
// 	}
// private:
// 	double _rate;
// };

// int main()
// {
// 	// 函数对象
// 	double rate = 0.015;
// 	Rate r1(rate);
// 	cout << r1(10000, 2) << endl;

// 	// lambda
// 	auto r2 = [rate](double monty, int year)->double
// 	{
// 		return monty * rate * year;
// 	};

// 	cout << r2(10000, 2) << endl;

// 	int x = 1, y = 2;
// 	auto r3 = [=](double monty, int year)->double
// 	{
// 		return monty * rate * year;
// 	};

// 	cout << r3(10000, 2) << endl;


// 	return 0;
// }




/////////////////////////////////////////////////////////////////////////
// 
#include<functional>

int f(int a, int b)
{
	return a + b;
}

struct Functor
{
public:
	int operator() (int a, int b)
	{
		return a + b;
	}
};

class Plus
{
public:
	static int plusi(int a, int b)
	{
		return a + b;
	}

	double plusd(double a, double b)
	{
		return a + b;
	}
};

// int main()
// {
// 	// 包装可调用对象
// 	function<int(int, int)> f1 = f;
// 	function<int(int, int)> f2 = Functor();
// 	function<int(int, int)> f3 = [](int a, int b) {return a + b; };

// 	cout << f1(1, 1) << endl;
// 	cout << f2(1, 1) << endl;
// 	cout << f3(1, 1) << endl;

// 	// 包装静态成员函数
// 	function<int(int, int)> f4 = &Plus::plusi;
// 	cout << f4(1, 1) << endl;

// 	// 包装非静态成员函数
// 	function<double(Plus*, double, double)> f5 = &Plus::plusd;
// 	Plus pd;
// 	cout << f5(&pd, 1.1, 1.1) << endl;


// 	function<double(Plus, double, double)> f6 = &Plus::plusd;
// 	cout << f6(pd, 1.1, 1.1) << endl;
// 	cout << f6(Plus(), 1.1, 1.1) << endl;

// 	return 0;
// }




using placeholders::_1;
using placeholders::_2;
using placeholders::_3;

int Sub(int a, int b)
{
	return (a - b) * 10;
}

int SubX(int a, int b, int c)
{
	return (a - b - c) * 10;
}

int main()
{
	auto sub1 = bind(Sub, _1, _2);
	cout << sub1(10, 5) << endl;

	// bind 本质返回的一个仿函数对象
	// 调整参数顺序（不常用）
	// _1代表第一个实参
	// _2代表第二个实参
	// ...
	auto sub2 = bind(Sub, _2, _1);
	cout << sub2(10, 5) << endl;

	// 调整参数个数 （常用）
	auto sub3 = bind(Sub, 100, _1);
	cout << sub3(5) << endl;

	auto sub4 = bind(Sub, _1, 100);
	cout << sub4(5) << endl;

	// 分别绑死第123个参数
	auto sub5 = bind(SubX, 100, _1, _2);
	cout << sub5(5, 1) << endl;

	auto sub6 = bind(SubX, _1, 100, _2);
	cout << sub6(5, 1) << endl;

	auto sub7 = bind(SubX, _1, _2, 100);
	cout << sub7(5, 1) << endl;

	function<double(Plus, double, double)> f6 = &Plus::plusd;
	Plus pd;
	cout << f6(pd, 1.1, 1.1) << endl;
	cout << f6(Plus(), 1.1, 1.1) << endl;

	// bind一般用于，绑死一些固定参数
	function<double(double, double)> f7 = bind(&Plus::plusd, Plus(), _1, _2);
	cout << f7(1.1, 1.1) << endl;

	//auto func1 = [](double rate, double monty, int year)->double {return monty * rate * year;};
	auto func1 = [](double rate, double monty, int year)->double {
		double ret = monty;
		for (int i = 0; i < year; i++)
		{
			 ret += ret * rate;
		}

		return ret - monty;
	};

	function<double(double)> func3_1_5 = bind(func1, 0.015, _1, 3);
	function<double(double)> func5_1_5 = bind(func1, 0.015, _1, 5);
	function<double(double)> func10_2_5 = bind(func1, 0.025, _1, 10);
	function<double(double)> func20_3_5 = bind(func1, 0.035, _1, 30);

	cout << func3_1_5(1000000) << endl;
	cout << func5_1_5(1000000) << endl;
	cout << func10_2_5(1000000) << endl;
	cout << func20_3_5(1000000) << endl;

	return 0;
}